/*
 * Copyright 2021 The Chromium OS Authors
 *
 * SPDX-License-Identifier: Apache-2.0
 */
/* Standard includes. */
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>
/**/
#include "FreeRTOS.h"
/**/
#include "smf.h"
#include "util.h"

/*debug printf*/
#define TAG_SMF                          "SMF"
#define DebugPrint_SMF(fmt,...)          printWithTimestamp(TAG_SMF,fmt, ##__VA_ARGS__) // 带时间戳
/*
 * Private structure (to this file) used to track state machine context.
 * The structure is not used directly, but instead to cast the "internal"
 * member of the smf_ctx structure.
 */
struct internal_ctx {
	bool new_state : 1;
	bool terminate : 1;
	bool exit      : 1;
	bool handled   : 1;
};

/**
 * @brief Execute all ancestor entry actions
 *
 * @param ctx State machine context
 * @param target The entry actions of this target's ancestors are executed
 * @return true if the state machine should terminate, else false
 */
// __unused static bool smf_execute_ancestor_entry_actions(
// 		struct smf_ctx *const ctx, const struct smf_state *target)
// {
// 	struct internal_ctx * const internal = (void *) &ctx->internal;

// 	for (const struct smf_state *to_execute = get_last_of(target);
// 	     to_execute != NULL && to_execute != target;
// 	     to_execute = get_child_of(target, to_execute)) {
// 		/* Execute parent state's entry */
// 		if (!last_state_share_paren(ctx, to_execute) && to_execute->entry) {
// 			to_execute->entry(ctx);

// 			/* No need to continue if terminate was set */
// 			if (internal->terminate) {
// 				return true;
// 			}
// 		}
// 	}

// 	return false;
// }

/**
 * @brief Execute all ancestor run actions
 *
 * @param ctx State machine context
 * @param target The run actions of this target's ancestors are executed
 * @return true if the state machine should terminate, else false
 */
// __unused static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx)
// {
// 	struct internal_ctx * const internal = (void *) &ctx->internal;
// 	/* Execute all run actions in reverse order */

// 	/* Return if the current state switched states */
// 	if (internal->new_state) {
// 		internal->new_state = false;
// 		return false;
// 	}

// 	/* Return if the current state terminated */
// 	if (internal->terminate) {
// 		return true;
// 	}

// 	if (internal->handled) {
// 		/* Event was handled by this state. Stop propagating */
// 		internal->handled = false;
// 		return false;
// 	}


// 	internal->new_state = false;
// 	/* All done executing the run actions */

// 	return false;
// }

/**
 * @brief Execute all ancestor exit actions
 *
 * @param ctx State machine context
 * @param target The exit actions of this target's ancestors are executed
 * @return true if the state machine should terminate, else false
 */
// __unused static bool smf_execute_ancestor_exit_actions(
// 		struct smf_ctx *const ctx, const struct smf_state *target)
// {
// 	struct internal_ctx * const internal = (void *) &ctx->internal;

// 	/* Execute all parent exit actions in reverse order */

// 	for (const struct smf_state *tmp_state = ctx->current->parent;
// 	     tmp_state != NULL;
// 	     tmp_state = tmp_state->parent) {
// 		if ((target == NULL || !share_paren(target->parent, tmp_state)) &&
// 		    tmp_state->exit) {
// 			tmp_state->exit(ctx);

// 			/* No need to continue if terminate was set */
// 			if (internal->terminate) {
// 				return true;
// 			}
// 		}
// 	}
// 	return false;
// }

void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state)
{
	struct internal_ctx * const internal = (void *) &ctx->internal;


#ifdef CONFIG_SMF_INITIAL_TRANSITION
	/*
	 * The final target will be the deepest leaf state that
	 * the target contains. Set that as the real target.
	 */
	while (init_state->initial) {
		init_state = init_state->initial;
	}
#endif
	internal->exit = false;
	internal->terminate = false;
	ctx->current = init_state;
	ctx->previous = NULL;
	ctx->terminate_val = 0;

	// if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) {
	// 	internal->new_state = false;

	// 	if (smf_execute_ancestor_entry_actions(ctx, init_state)) {
	// 		return;
	// 	}
	// }

	/* Now execute the initial state's entry action */
	if (init_state->entry) {
		init_state->entry(ctx);
	}
}

void smf_set_state(struct smf_ctx *const ctx, const struct smf_state *target)
{
	struct internal_ctx * const internal = (void *) &ctx->internal;

	/*
	 * It does not make sense to call set_state in an exit phase of a state
	 * since we are already in a transition; we would always ignore the
	 * intended state to transition into.
	 */
	if (internal->exit) {
		DebugPrint_SMF("Calling %s from exit action", __func__);
		return;
	}

	internal->exit = true;

	/* Execute the current states exit action */
	if (ctx->current->exit) {
		ctx->current->exit(ctx);

		/*
		 * No need to continue if terminate was set in the
		 * exit action
		 */
		if (internal->terminate) {
			return;
		}
	}

	// if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) {
	// 	internal->new_state = true;

	// 	if (smf_execute_ancestor_exit_actions(ctx, target)) {
	// 		return;
	// 	}
	// }

	internal->exit = false;

#ifdef CONFIG_SMF_INITIAL_TRANSITION
	/*
	 * The final target will be the deepest leaf state that
	 * the target contains. Set that as the real target.
	 */
	while (target->initial) {
		target = target->initial;
	}
#endif

	/* update the state variables */
	ctx->previous = ctx->current;
	ctx->current = target;

	// if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) {
	// 	if (smf_execute_ancestor_entry_actions(ctx, target)) {
	// 		return;
	// 	}
	// }

	/* Now execute the target entry action */
	if (ctx->current->entry) {
		ctx->current->entry(ctx);
		/*
		 * If terminate was set, it will be handled in the
		 * smf_run_state function
		 */
	}
}

void smf_set_terminate(struct smf_ctx *ctx, int32_t val)
{
	struct internal_ctx * const internal = (void *) &ctx->internal;

	internal->terminate = true;
	ctx->terminate_val = val;
}

void smf_set_handled(struct smf_ctx *ctx)
{
	struct internal_ctx *const internal = (void *)&ctx->internal;

	internal->handled = true;
}

int32_t smf_run_state(struct smf_ctx *const ctx)
{
	struct internal_ctx * const internal = (void *) &ctx->internal;

	/* No need to continue if terminate was set */
	if (internal->terminate) {
		return ctx->terminate_val;
	}

	if (ctx->current->run) {
		ctx->current->run(ctx);
	}

	// if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) {
	// 	if (smf_execute_ancestor_run_actions(ctx)) {
	// 		return ctx->terminate_val;
	// 	}
	// }

	return 0;
}
